<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\BaseController;
use App\Jobs\SearchJob;
use App\Models\Animal;
use App\Models\Article;
use App\Models\ArticleRelateCircle;
use App\Models\Circle;
use App\Models\City;
use App\Models\UserJoinCircle;
use App\Models\VoiceTranslate;
use App\Mongo\CircleMon;
use App\Services\Circle\CircleJoinUserCoverService;
use App\Services\Circle\GetLotteryUserService;
use App\Services\SafeCheckService;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class CircleController extends BaseController
{

    public function index(Request $request, $action = null, $is_raw_return = false) {
        $input = $request->input();
        $title = $input['title'] ?? '';
        $action = $action ?: $request->input('action');
        $user_id = $request->input('user_id') ?: $this->getUserId();
        $city = $new_item = $area_circle = null;
        $is_activity = $request->input('is_activity', 0);
        $is_hot_activity = $request->input('is_hot_activity', 0);
        $page = \request('page', 1);
        $order_by_value = 'desc';
        $focus_query = true;
        $extra_circle_list = [];
        if ($action == 'nearby' || $action == 'rec' || $action == 'belong_city' ) {
            $this->validate($request, [
                'longitude' => 'required',
                'latitude' => 'required'
            ]);
        }

        if ($action == 'search') {
            $this->validate($request, [
                'title' => 'required',
            ]);
        }

        $circle = new Circle();
        if ($action == 'nearby') {
            $circle_list = CircleMon::where('location', 'near', [
                '$geometry' => [
                    'type' => 'Point',
                    'coordinates' => [
                        floatval($input['longitude']),
                        floatval($input['latitude'])
                    ],
                ],
                '$maxDistance' => 100000,
            ])->where('status', Circle::STATUS_SUCCESS)->select('id')->paginate(per_page());
            $arr_id = array_column($circle_list->items(), 'id');
            $circle = $circle->whereIn('id', $arr_id)->orderBy(\DB::raw('FIND_IN_SET(id, "' . implode(",", $arr_id) . '"' . ")"));
            $focus_query = false;
            $request->merge(['page' => 1]);
        } else if ($action == 'rec') {
            $city = get_city_by_position($input);
            if ($page == 1 && $city) {
                $area_circle = Circle::where('is_area', 1)->where('city', $city)
                    ->withCount(['is_focus' => function($qr) use($user_id){
                        $qr->where('user_id', $user_id);
                    }])->get();
                foreach ($area_circle as &$item) {
                    $item->join_users = CircleJoinUserCoverService::handle($item->id);
                }
            }

            $circle = $circle->where('is_area', 0)
                ->orderBy('sort', 'desc')->orderBy('rec_weight', 'desc');

            $focus_query = false;
        } else if($action == 'hot') {
            $circle = $circle->where('is_area', 0)->orderBy('join_count', 'desc');
            $focus_query = false;
        } else if($action == 'category') {
            $order_by_value = 'asc';
            $this->validate($request, [
                'circle_category_id' => 'required'
            ]);
            $circle_category_id = $request->input('circle_category_id');
            $city = '';
            if ($circle_category_id == 1) {
                $city = get_city_by_position($input);
                if ($page == 1 && $city)
                    $area_circle = Circle::where('is_area', 1)->where('city', $city)
                        ->withCount(['is_focus' => function($qr) use($user_id){
                            $qr->where('user_id', $user_id);
                        }])->get();

            }
            $circle = Circle::select('circles.*')->join('circle_category_relates', function ($join) use($circle_category_id) {
                $join->on('circle_category_relates.circle_id', 'circles.id')->where('circle_category_id', $circle_category_id);
            })->when($circle_category_id == 1 && $city, function ($q) use($city){
                $q->where('city', '!=', $city);
            })->orderBy('sort', 'desc')->orderBy('rec_weight', 'desc');
            $focus_query = false;
        } else if($action == 'belong_city'){
            $city = \request('city', get_city_by_position($input));
//            ->whereDoesntHave('is_focus', function ($q) use($user_id) {
//                $q->where('user_id', $user_id);
//            })
            $circle = $circle->where('is_area', 1)->where('city', $city)->where('id', '<=', 371);
        } else if($action == 'my_circle') {
            $circle = Circle::join('user_join_circles', function ($join) use($user_id){
                $join->on('circles.id', 'user_join_circles.circle_id')->where('user_join_circles.user_id', $user_id);
            });
        } else if($action == 'my_circle_order_by_article') {
            $city = \request('city', get_city_by_position($input));
            $arr_circle_id = ArticleRelateCircle::selectRaw('circle_id, count(article_id) as total')->where('article_user_id' , $user_id)->groupBy('circle_id')
                ->orderBy('total', 'desc')->limit(3)->get()->pluck('circle_id')->all();
            $circle = Circle::when(empty($arr_circle_id), function ($q) use($city) {
                $q->where('is_area', 1)->where('city', $city)->where('id', '<=', 3065);
            })->when(!empty($arr_circle_id), function ($q) use($arr_circle_id) {
                $q->whereIn('id', $arr_circle_id)->orderBy(\DB::raw('FIND_IN_SET(id, "' . implode(",", $arr_circle_id) . '"' . ")"));
            });
            $extra_circle_list = Circle::select(['id', 'title', 'logo'])->where('is_area', 1)->where('city', $city)->where('id', '<=', 371)->get();

        } else if($action == 'rand_rec') {
            $circle = $circle->where('is_area', '=', 0)->where('is_top_80', 1)->inRandomOrder()->orderBy('sort', 'desc')->orderBy('rec_weight', 'desc');
        } else if($action == 'share_animal_rec') {
            $this->validate($request, [
                'animal_id' => 'required',
            ]);
            $animal_id = \request('animal_id');
            $animal = Animal::with('category')->find($animal_id);
            if (!$animal) {
                return $this->failed('宠物不存在');
            }
//            $city = \request('city', get_city_by_position($input));
            $arr_id = [];
            if (in_array($animal->parent_category_id, [Animal::CAT])) {
//                $circle = Circle::where('is_area', 1)->where('city', $city)->where('title', 'like', '%猫咪%')->where('id', '<=', 3065)->first();
                array_push($arr_id, 2289);
            } else if (in_array($animal->parent_category_id, [Animal::DOG])) {
//                $circle = Circle::where('is_area', 1)->where('city', $city)->where('title', 'like', '%狗狗%')->where('id', '<=', 3065)->first();
                array_push($arr_id, 2288);
            }
            if (in_array($animal->parent_category_id, [Animal::CAT, Animal::DOG])) {
                $cate_title = $animal->category->title ?? '';
                $cat_map = cate_map();
                if (isset($cat_map[$cate_title]))
                    $cate_title = $cat_map[$cate_title];

                $circle = Circle::where('title', 'like', '%'.$cate_title.'%')->first();
                $circle && array_push($arr_id, $circle->id);
            } else if(in_array($animal->parent_category_id, [Animal::SMALL])) {
                $map = ['2297' => '龙猫', '2309' => '仓鼠宠友圈', '2311' => '刺猬宠友圈'
                    , '2313'=>'鹦鹉宠友圈', '2312'=> '兔子宠友圈', '2310'=> '蜜袋鼯宠友圈', '2302' => '羊驼宠友圈'];
                $arr_id = array_merge($arr_id, array_keys($map));
            }   else if(in_array($animal->parent_category_id, [Animal::CREEP])) {
                $map = ['2300' => '守宫宠友圈', '2304' => '玉米蛇宠友圈', '2307' => '猪鼻蛇宠友圈'
                    , '2305'=>'鬃狮蜥宠友圈', '2301'=> '蜘蛛宠友圈', '2303'=> '乌龟宠友圈'];
                $arr_id = array_merge($arr_id, array_keys($map));
            }   else if(in_array($animal->parent_category_id, [Animal::WATER])) {
                $map = ['2308'=> '蜘蛛宠友圈', '2303'=> '乌龟宠友圈'];
                $arr_id = array_merge($arr_id, array_keys($map));
            }
            $circle = Circle::whereIn('id', $arr_id)->orderBy(\DB::raw('FIND_IN_SET(id, "' . implode(",", $arr_id) . '"' . ")"));
        } else if($action == 'voice_translate') {
            $city = \request('city', get_city_by_position($input));
            $arr_circle_id = [];
            $circle = Circle::where('is_area', 1)->where('city', $city)->where('id', '<=', 371)->first();
            $circle && array_push($arr_circle_id, $circle->id);
            $animal_type = $request->input('animal_type',VoiceTranslate::TYPE_CAT);
            if ($animal_type == 1) {
                $circle = Circle::where('is_area', 1)->where('city', $city)->where('title', 'like', '%猫咪%')->where('id', '<=', 3065)->first();
                $circle && array_push($arr_circle_id, $circle->id);
                array_push($arr_circle_id, Circle::CAT_ID);
            } else {
                $circle = Circle::where('is_area', 1)->where('city', $city)->where('title', 'like', '%狗狗%')->where('id', '<=', 3065)->first();
                $circle && array_push($arr_circle_id, $circle->id);
                array_push($arr_circle_id, Circle::DOG_ID);
            }
            $circle = Circle::whereIn('id', $arr_circle_id)->orderBy(\DB::raw('FIND_IN_SET(id, "' . implode(",", $arr_circle_id) . '"' . ")"));
        }
        $list = $circle->when($title, function ($q) use($title, $user_id) {
            $q->where('title', 'like', '%' . $title . '%')->orderBy('join_count', 'desc');
            $this->dispatch(new SearchJob($user_id, $title));
        })->when($focus_query, function ($q) use($user_id) {
            $q->withCount(['is_focus' => function($qr) use($user_id){
                $qr->where('user_id', $user_id);
            }]);
        })->where('circles.is_activity', $is_activity)
            ->when($is_activity, function ($q) {
                $q->where('is_hot_activity', 1);
            })
            ->where('status', Circle::STATUS_SUCCESS)
            ->orderBy('circles.id', $order_by_value)->paginate(per_page());

        foreach ($list as &$item) {
            if($action == 'my_circle') {
                $item->article = ArticleRelateCircle::join('articles', function ($q) {
                    $q->on('article_relate_circles.article_id', 'articles.id');
                })->where('circle_id', $item->id)->select('file_path')
                    ->orderBy('article_weight', 'desc')->orderBy('articles.id', 'desc')->limit(3)->get();
            }
            $item->join_users = [];
            if (in_array($action, ['nearby', 'hot', 'rec', 'activity'])) {
                $item->join_users = CircleJoinUserCoverService::handle($item->id);
            }

        }

        if(in_array($action, ['rec', 'category']) && $page == 1 ) {
            $mer_list = collect($area_circle)->merge($list->items());
            $arr = [
                'list' => $mer_list,
                'total' => $list->total(),
                'has_more_page' => $list->hasMorePages(),
                'extra' => null
            ];
            return $this->success($arr);
        }
        if ($is_raw_return)
            return $list;

        $total = $has_more_page = false;
        if($action == 'nearby') {
            $total = $circle_list->total();
            $has_more_page = $circle_list->hasMorePages();
        }

        return $this->paginate($list, ['city' => $city, 'extra_circle_list' => $extra_circle_list], $total, $has_more_page);
    }

    public function info(Request $request)
    {
        $this->validate($request, [
            'id' => 'required'
        ]);
        $user_id = $this->getUserId();
        $id = $request->input('id');
        $info = $temp = Circle::with(['user' => function($q) {
                $q->select('id','nickname', 'weixin', 'avatar_url');
            }, 'user.animal' => function($q) {
                $q->select('user_id', 'title', 'birthday', 'category_title');
            }])
            ->withCount(['user_article' => function($q) use($user_id) {
                $q->where('article_user_id', $user_id);
            }])
            ->withCount(['is_focus' => function($q) use($user_id){
                $q->where('user_id', $user_id);
            }])->find($id);
        if (!$info)
            return $this->failed('圈子不存在');

        $temp->join_users = CircleJoinUserCoverService::handle($id);
        Circle::where('id', $id)->increment('pv');

        if ($temp->is_activity) {
            $temp->lottery_result = GetLotteryUserService::handle($id, $temp->lottery);
            $temp->has_lottery = 1;
            $lottery_txt = ['first' => '一等奖', 'second' => '二等奖', 'third' => '三等奖'];
            $temp->win_lottery = 0;
            if ($temp->lottery_result) {
                foreach ($temp->lottery_result as $key => $child) {
                    if ( is_array($child)) {
                        foreach ($child as $item) {
                            if (isset($item['id'])) {
                                if ($item['id'] == $user_id) {
                                    $temp->win_lottery = $key;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            $temp['win_lottery_txt'] = $lottery_txt[$temp->win_lottery] ?? '';
        }
        return $this->success($temp);
    }


    public function store(Request $request) {
       $this->validate($request, [
           'title' => 'required',
           'desc' => 'required',
           'logo' => 'required',
           'longitude' => 'required',
           'latitude' => 'required'
       ]);
       $input = $request->input();
        if (!empty($input['title'])) {
            $content = $input['title'] . $input['desc'];
            $hit = SafeCheckService::handle(['type' => 'text', 'content' => $content]);
            if ($hit)
                return $this->failed('发布内容包含敏感词');
        }

       $user = $this->getUser();
       $input['user_id'] = $user->id;
       $id = \request("id");
       $arr = reverse_geocode($input['longitude'], $input['latitude'], true);
       $city = $arr['city'];
       if (!$city)
           return $this->failed('经纬度获取城市失败');
       $city_code = City::get_code_by_name($city);
       if (!$city_code) {
           \Log::error('cities表该城市不存在:' . $city);
           return $this->failed('该城市不支持');
       }
       $input['city_code'] = $city_code;
       $input['city'] = $city;
       $input['detail_address'] = $arr['formatted_address'];
       return DB::transaction(function () use($id, $input, $city_code, $city) {
           $exist_id = Circle::where('title', $input['title'])->value('id');
           if ($id) {
               if ($exist_id != $id)
                   return $this->failed('圈子标题已经存在，请换一个');

               $info = Circle::where('id', $id)->first();
               $info->update($input);

               CircleMon::where('id', $id)->update([
                   'city' => $city,
                   'location' => [
                       'type' => 'Point',
                       'coordinates' => [
                           floatval($input['longitude']),
                           floatval($input['latitude'])
                       ]
                   ],
                   'city_code' => $city_code
               ]);

           } else {
               if ($exist_id )
                   return $this->failed('圈子标题已经存在，请换一个');
               $input['join_count'] = 1;
               $info = Circle::create($input);
               $id = $info->id;
               $user = $this->getUser();
               UserJoinCircle::create([
                   'user_id' => $user->id,
                   'circle_id' => $id,
                   'is_owner' => 1
               ]);
               CircleMon::create([
                   'id' => intval($id),
                   'city' => $city,
                   'status' => Circle::STATUS_WAIT_AUDIT,
                   'location' => [
                       'type' => 'Point',
                       'coordinates' => [
                           floatval($input['longitude']),
                           floatval($input['latitude'])
                       ]
                   ],
                   'city_code' => $city_code
               ]);
           }
           return $this->success(['id' => $id]);
       });
   }

   public function join(Request $request) {
        $id = $request->input('id');
        $model = Circle::find($id);
        if (!$model)
            return $this->failed('id对应的对象不存在');

        $user = $this->getUser();
        $user_id = $user->id;

        if ($model->user_id == $user_id)
            return $this->failed('当前圈子属于自己，不能取消加入');

        $info = UserJoinCircle::where('user_id', $user_id)->where('circle_id', $id)->first();
        if ($info) {
            $num = -1;
            $info->delete();
            $act = 'cancel';
        } else {
            $num = 1;
            UserJoinCircle::create([
                'user_id' => $user_id,
                'circle_id' => $id
            ]);
            $act = 'ok';
        }
       \Cache::forget(Circle::CACHE_CIRCLE_COVER_USER . "_" . $id);
        $join_count = $model->join_count + $num;
        $model->join_count = $join_count > 0 ? $join_count : 0;
        $model->save();
        $user->circle_count += $num;
        if ($user->circle_count >= 0)
            $user->save();

        return $this->success([
            'act' => $act
        ]);
   }
   
}

